
package com.hlkj.pay.task;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.pay.app.order.impl.OrderNotifyProcessHandler;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.common.OrderStatusDto;
import com.hlkj.pay.dto.merchant.MerchantAccessDto;
import com.hlkj.pay.dto.merchant.RouterConfigDto;
import com.hlkj.pay.dto.order.OrderFundDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppDO;
import com.hlkj.pay.infrastructure.model.order.*;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.payment.MerchantPaymentDO;
import com.hlkj.pay.infrastructure.model.payment.MerchantPaymentDetailDO;
import com.hlkj.pay.service.merchant.IMerchantAccessAuthService;
import com.hlkj.pay.service.merchant.IMerchantAccessService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.order.*;
import com.hlkj.pay.service.payment.IMerchantPaymentService;
import com.hlkj.pay.service.user.IUserCouponService;
import com.hlkj.pay.service.user.IUserRechargeService;
import com.hlkj.pay.util.MerchantAppChannelRouterUtil;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/10/29 10:43
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AdPayOrderScheduledTasks {

    private final IPayOrderService payOrderService;

    private final IRefundOrderService refundOrderService;

    private final IMerchantAccessService merchantAccessService;

    private final ISettleOrderService settleOrderService;

    private final IMerchantPaymentService merchantPaymentService;

    private final IPayOrderFundService payOrderFundService;

    private final ITransferOrderService transferOrderService;

    private final IWithdrawOrderService withdrawOrderService;

    private final OrderNotifyProcessHandler orderNotifyProcessHandler;

    private final IMerchantApplicationService merchantApplicationService;

    private final IMerchantAccessAuthService merchantAccessAuthService;

    private final IUserCouponService userCouponService;

    private final IUserRechargeService userRechargeService;

    private final CommonTasks commonTasks;


    @Value("${hlkj.pay.test:false}")
    private boolean payTest;

    @Value("${server.port:8020}")
    private String serverPort;

    @Value("${hlkj.task.port:8020}")
    private String taskPort;

    @Value("${hlkj.domain}")
    private String domain;

    @Value("${spring.profiles.active}")
    private String active;

    // /**
    //  * 话费充值状态同步
    //  */
    // @Scheduled(cron = "*/10 * * * * *")
    // public void phoneChargeStatusTask() {
    //     // if (!serverPort.equals(taskPort)) {
    //     //     log.info("当前task port 非目标port serverPort:{},taskPort:{}", serverPort, taskPort);
    //     //     return;
    //     // }
    //     if(!active.equals("prod")){
    //         log.info("话费充值状态查询开始");
    //         // 查询充值中的状态
    //         UserTeleChargeOrderQueryDto userTeleChargeOrderQueryDto = new UserTeleChargeOrderQueryDto();
    //         userTeleChargeOrderQueryDto.setState(UserEnum.RECHARGE_STATUS.DOING.getCode());
    //         userTeleChargeOrderQueryDto.setStartQueryTime(DateUtils.shanghaiStartDate(DateUtil.format(new Date(),DatePattern.NORM_DATE_PATTERN), DatePattern.NORM_DATE_PATTERN));
    //         userTeleChargeOrderQueryDto.setEndQueryTime(DateUtils.shanghaiEndDate(DateUtil.format(new Date(),DatePattern.NORM_DATE_PATTERN), DatePattern.NORM_DATE_PATTERN));
    //         List<UserTeleChargeOrderDO> userTeleChargeOrderDOList = userRechargeService.queryList(userTeleChargeOrderQueryDto);
    //         if(CollUtil.isNotEmpty(userTeleChargeOrderDOList)){
    //             for(UserTeleChargeOrderDO userTeleChargeOrderDO:userTeleChargeOrderDOList){
    //                 // 查询状态
    //                 commonTasks.syncAdChargeStatus(userTeleChargeOrderDO);
    //             }
    //         }
    //     }
    // }

    /**
     * 定时清理过期话费卷
     */
//     @Scheduled(cron = "0 10 0 * * *")
//     public void cronTask() {
// //        if(!active.equals("prod")) {
//             log.info("开始清理过期话费卷");
//             TimeZone shanghaiZone = TimeZone.getTimeZone("Asia/Shanghai");
//             TimeZone.setDefault(shanghaiZone);
//             Date inputDate = DateUtil.date();
//             Date beginOfMonth = DateUtil.beginOfMonth(inputDate);
//             log.info("开始清理过期话费卷, 过期时间 {}", beginOfMonth.getTime());
//             userCouponService.cleanExpireCopons(beginOfMonth.getTime());
// //        }
//     }

    // @Scheduled(cron = "*/20 * * * * *")
    // public void cronTask() {
    //     if (!payTest) {
    //         log.info("非测试环境订单自动支付任务开始 date:{}", LocalDateTime.now());
    //         return;
    //     }
    //     log.info("测试环境订单自动支付任务开始 date:{}", LocalDateTime.now());
    //     AdPayOrderQueryDto adPayOrderQueryDto = new AdPayOrderQueryDto();
    //     adPayOrderQueryDto.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
    //     adPayOrderQueryDto.setPageNo(1);
    //     adPayOrderQueryDto.setPageSize(1000);
    //     PageResult<AdPayOrderDto> adPayOrderDOPageResult = payOrderService.queryPage(adPayOrderQueryDto);
    //     List<AdPayOrderDto> list = adPayOrderDOPageResult.getList();
    //     if (CollectionUtils.isEmpty(list)) {
    //         log.info("测试环境订单自动支付任务结束 没有需要执行的任务 date:{}", LocalDateTime.now());
    //         return;
    //     }
    //     log.info("测试环境订单自动支付任务 需要执行的任务数量 size:{}, date:{}", list.size(), LocalDateTime.now());
    //     list.stream().forEach(adPayOrderDto -> {
    //         updateData(adPayOrderDto);
    //     });
    // }
    // @Async("taskExecutor")
    // void updateData(AdPayOrderDto adPayOrderDto) {
    //     AdPayOrderDO updatePayOrderDO = new AdPayOrderDO();
    //     updatePayOrderDO.setId(adPayOrderDto.getId());
    //     updatePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
    //     updatePayOrderDO.setPayAmount(adPayOrderDto.getAmount());
    //     updatePayOrderDO.setSuccessTime(System.currentTimeMillis());
    //     adPayOrderService.updatePayOrder(adPayOrderDto.getMchOrderNo(), updatePayOrderDO);
    //     AdPayOrderDO adPayOrderDO = adPayOrderDto;
    //     adPayOrderDO.setPayAmount(adPayOrderDto.getAmount());
    //     adPayOrderHandler.paySuccess(adPayOrderDO);
    // }

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 核心线程数
        executor.setMaxPoolSize(20); // 最大线程数
        executor.setQueueCapacity(1000); // 队列容量
        executor.setKeepAliveSeconds(60); // 线程空闲时间
        executor.setThreadNamePrefix("Async-Order"); // 线程名称前缀
        executor.initialize();
        return executor;
    }

    @Async("taskExecutor")
    public void processOrderNotifyMessageLast(OrderStatusDto orderStatusDto) {
        PayOrderEnums.ORDER_STATUS_TYPE orderStatusType = PayOrderEnums.ORDER_STATUS_TYPE.from(orderStatusDto.getOrderStatusType());
        log.info(orderStatusType.getMsg() + " 首次通知 orderNo:{}", orderStatusDto.getOrderNo());
        processOrderNotifyMessage(orderStatusDto);
    }

    /**
     * 商户通道轮询任务
     * @param payOrderDO
     * @param payWayDO
     * @return
     */
    @Async("taskExecutor")
    public CommonResult<Void> merchantChannelRoute(PayOrderDO payOrderDO,PayWayDO payWayDO,MerchantAccessAuthDO merchantAccessAuthNow, String sn,MerchantAppDO merchantAppDO) {
        String payWayCode = payWayDO.getCode();
        MerchantAppChannelDO merchantAppSubChannelDO = null;
        String mchChannelCode = payOrderDO.getMchChannelCode();
        if (StringUtils.hasText(mchChannelCode)) {
            merchantAppSubChannelDO = merchantApplicationService.queryAppChannelDetail(mchChannelCode);
            if (merchantAppSubChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }
            if (!merchantAppSubChannelDO.getPayWayCodes().contains(payWayCode)) {
                log.info("merchantChannelRoute 支付方式 payWayCode:{},不存在", payWayCode);
                return CommonResult.error(PayResultCode.PAY_WAY_NOT_EFFECT);
            }

            CommonResult<MerchantAppChannelDO> commonResult = null;
            MerchantAccessAuthDO merchantAccessAuthDO = null;
            // 通道路由配置
            RouterConfigDto routerConfigDto = merchantAppDO.getRouterConfigDto();
            // 轮询策略 0：系统默认 1 顺序单个 2 随机多个
            if(routerConfigDto == null || routerConfigDto.getRouterStrategy() == 0){
                return CommonResult.success();
            }
            // 轮询策略 0：系统默认 1 顺序单个 2 随机多个
            Integer routerStrategy = routerConfigDto.getRouterStrategy();
            // 轮询方式 0:机构通道轮询 1:AT通道轮询
            Integer routerType = routerConfigDto.getRouterType();
            // 轮询方式 0:机构通道轮询 1:AT通道轮询
            Integer routerOrder = routerConfigDto.getRouterOrder();
            // 交易失败是否自动切换或关闭 1:是 0:否
            Integer autoDealFailedNext = routerConfigDto.getAutoDealFailedNext();

            MerchantEnum.ROUTE_TYPE routeType = MerchantEnum.ROUTE_TYPE.from(routerStrategy);
            switch (routeType){
                case DEFAULT:
                    break;
                case SEQ_SINGLE:
                    log.info("merchantChannelRoute getSeqChannel go");
                    if(routerOrder == null){
                        routerOrder = 0;
                    }
                    // 机构通道轮询
                    if(routerType == null ||  routerType == 0){
                        log.info("merchantChannelRoute getSeqChannel APP通道 go");
                        // 是否自动切换下一个
                        if(autoDealFailedNext != null && autoDealFailedNext == 1){
                            // 获取开启通道集合
                            List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), 1, null);
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                            }
                            // 支付方式校验
                            merchantAppChannelList = merchantAppChannelList.stream().filter(merchantAppChannelDO -> merchantAppChannelDO.getPayWayCodes().contains(payWayCode))
                                    .collect(Collectors.toList());
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                log.info("merchantChannelRoute getSeqChannel 支付方式 payWayCode:{},不存在", payWayCode);
                                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
                            }

                            if(merchantAppChannelList.size() > 1){
                                log.info("merchantChannelRoute getSeqChannel APP通道 商户轮询配置顺序单个只允许一个开启的通道");
                                return CommonResult.error(0,"商户轮询配置顺序单个只允许一个开启的通道");
                            }
                            // 查询当前商户下所有通道
                            merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), null,null);
                            commonResult = getSeqChannel(mchChannelCode,sn,merchantAppChannelList,payWayCode,routerOrder);
                            if(!commonResult.isSuccess()){
                                log.info("merchantChannelRoute getSeqChannel APP通道 fail:{}",commonResult.getMsg());
                                return CommonResult.error(0,commonResult.getMsg());
                            }
                            // 成功获取下一个通道
                            MerchantAppChannelDO channelNew = commonResult.getData();
                            if(!mchChannelCode.equals(channelNew.getChannelCode())){
                                // 关闭旧通道
                                merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                                // 开启新通道
                                merchantApplicationService.updateMerchantAppChannelStatus(channelNew.getCode(),1,payOrderDO.getSn(),payOrderDO.getAppId());
                                log.info("merchantChannelRoute getSeqChannel APP通道 suceess, close:{} ,open:{}",mchChannelCode,channelNew.getCode());
                            }
                        }
                    }else{
                        log.info("merchantChannelRoute getSeqChannel AT通道 go");
                        // 是否自动切换下一个
                        if(autoDealFailedNext != null &&  autoDealFailedNext == 1){
                            // 查询AT通道
                            List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), PayEnums.PAY_TYPE.fromByCode(payWayDO.getType()),CommonEnum.YES_NO_TYPE.YES.getCode(),null);
                            if(CollUtil.isEmpty(merchantAccessAuthList)){
                                return CommonResult.error(0,"商户轮询配置顺序单个AT通道不存在");
                            }
                            // 顺序单个只允许一个开启的通道
                            if(merchantAccessAuthList.size() > 1){
                                return CommonResult.error(0,"商户轮询配置顺序单个AT通道只允许一个开启的通道");
                            }
                            // 当前AT通道
                            merchantAccessAuthDO = merchantAccessAuthList.get(0);
                            // 获取开启通道集合
                            List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryChannelInfoList(merchantAppDO.getSn(), merchantAppDO.getAppId(), payOrderDO.getProviderCode(),
                                    payOrderDO.getChannelCode(), null, null);
                            if (CollectionUtils.isEmpty(merchantAppChannelList)) {
                                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
                            }
                            CommonResult<MerchantAccessAuthDO> AtCommonResult = getSeqAtChannel(payOrderDO,payWayDO,merchantAppSubChannelDO,payWayDO.getType(),routerType,routerOrder,merchantAppChannelList);
                            if(AtCommonResult.isSuccess() && AtCommonResult.getData() != null){
                                // 关闭旧AT通道
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                                log.info("merchantChannelRoute getSeqChannel AT通道 close:{}",JSONUtil.toJsonStr(merchantAccessAuthDO));
                                // 更新新AT通道
                                merchantAccessAuthDO = AtCommonResult.getData();
                                updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(1);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                                log.info("merchantChannelRoute getSeqChannel AT通道 open:{}",JSONUtil.toJsonStr(merchantAccessAuthDO));

                                if(merchantAccessAuthDO.getMerchantAppChannelDO() != null){
                                    // 关闭旧应用通道
                                    merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                                    log.info("merchantChannelRoute getSeqChannel APP通道 close:{}",mchChannelCode);
                                    // 开启新应用通道
                                    merchantApplicationService.updateMerchantAppChannelStatus(merchantAccessAuthDO.getMerchantAppChannelDO().getCode(),1,payOrderDO.getSn(),payOrderDO.getAppId());
                                    log.info("merchantChannelRoute getSeqChannel APP通道 open:{}",merchantAccessAuthDO.getMerchantAppChannelDO().getCode());
                                }
                            }else{
                                return CommonResult.error(0,AtCommonResult.getMsg());
                            }
                        }
                    }
                    break;
                case RANDOM_MULTIPLE:
                    log.info("merchantChannelRoute random go");
                    // 机构通道轮询
                    if(routerType == null ||  routerType == 0){
                        // 是否自动关闭
                        if(autoDealFailedNext != null && autoDealFailedNext ==  1){
                            merchantApplicationService.updateMerchantAppChannelStatus(mchChannelCode,0,payOrderDO.getSn(),payOrderDO.getAppId());
                            merchantApplicationService.updateMerchantAppChanneLimitRouter(mchChannelCode,0);
                            log.info("merchantChannelRoute random APP通道 close:{}",mchChannelCode);
                        }
                    }else{
                        // 关闭AT通道
                        if(autoDealFailedNext != null && autoDealFailedNext ==  1){
                            if(merchantAccessAuthNow != null){
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(merchantAccessAuthNow.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                                log.info("merchantChannelRoute random AT通道 close:{}",JSONUtil.toJsonStr(merchantAccessAuthNow));
                            }
                        }
                    }
                    break;
            }
        }
        return CommonResult.success();
    }


    /**
     * 顺序机构轮询
     * @param sn
     * @param merchantAppChannelList  数据库应用通道集合
     * @param payWayCode
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAppChannelDO> getSeqChannel(String mchChannelCode,String sn,List<MerchantAppChannelDO> merchantAppChannelList,String payWayCode,Integer routerOrder){
        // 通道编码顺序集合
        List<String> seqList = new ArrayList<>();
        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            seqList.add(merchantAppChannelDO.getCode());
        }
        log.info("merchantChannelRoute getSeqChannel seqList:{} ", JSONUtil.toJsonStr(seqList));
        // 位置
        int index = seqList.indexOf(mchChannelCode);
        log.info("merchantChannelRoute getSeqChannel start index:{},routerOrder:{} ",index,routerOrder);
        if(index == -1){
            log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常 当前通道不存在通道列表中sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常");
        }
        // 顺序
        if(routerOrder == 0){
            if(index == merchantAppChannelList.size() - 1){
                log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,末尾无法继续向下轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,末尾无法继续向下轮询");
            }
            index = index + 1;
        }else{
            if(index == 0){
                log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,首位无法继续向上轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,首位无法继续向上轮询");
            }
            index = index - 1;
        }
        log.info("merchantChannelRoute getSeqChannel start end:{} ",index);
        // index 区间判断
        if(index < 0 ||  index > merchantAppChannelList.size() - 1){
            log.error("merchantChannelRoute getSeqChannel 顺序单个机构轮询通道异常,轮询位置不在区间内 sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,轮询位置不在区间内");
        }
        return CommonResult.success(merchantAppChannelList.get(index));
    }


    /**
     * 当AT通道不满足需要切换应用通道时，轮训所有应用通道
     * @param mchChannelCode
     * @param sn
     * @param merchantAppChannelList
     * @param payWayDO
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAppChannelDO> getSeqAllChannel(String mchChannelCode,String sn,List<MerchantAppChannelDO> merchantAppChannelList,PayWayDO payWayDO,Integer routerOrder){
        // 通道编码顺序集合
        List<String> seqList = new ArrayList<>();
        // 通道编码 和  AT通道集合
        Map<String,List<MerchantAccessAuthDO>> authMap = new HashMap<>();
        MerchantAppChannelDO appChannelDO= null;
        List<MerchantAccessAuthDO> merchantAccessAuthList = null;
        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            // 查询所有AT通道
            merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppChannelDO.getAccessId(), PayEnums.PAY_TYPE.fromByCode(payWayDO.getType()),null,null);
            authMap.put(merchantAppChannelDO.getCode(),merchantAccessAuthList);
            seqList.add(merchantAppChannelDO.getCode());
        }
        // 获取索引位置
        int index = seqList.indexOf(mchChannelCode);
        log.info("merchantChannelRoute getSeqAllChannel start index:{},routerOrder:{} ",index,routerOrder);
        if(index < 0){
            log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常 当前通道不存在通道列表中,sn:{} ",sn);
            return CommonResult.error(0,sn+":顺序单个机构轮询通道异常");
        }

        // 顺序
        if(routerOrder == 0){
            if(index == merchantAppChannelList.size() - 1){
                log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常,末尾无法继续向下轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,末尾无法继续向下轮询");
            }
            for(int i=index+1; i<merchantAppChannelList.size();i++){
                appChannelDO = merchantAppChannelList.get(i);
                if(ObjectUtil.isEmpty(authMap.get(appChannelDO.getCode()))){
                    continue;
                }
                log.info("merchantChannelRoute getSeqAllChannel start end:{} ",index);
                return CommonResult.success(appChannelDO);
            }
        }else{
            if(index == 0){
                log.error("merchantChannelRoute getSeqAllChannel 顺序单个机构轮询通道异常,首位无法继续向上轮询 sn:{} ",sn);
                return CommonResult.error(0,sn+":顺序单个机构轮询通道异常,首位无法继续向上轮询");
            }
            for(int i=index-1; i>=0;i--){
                appChannelDO = merchantAppChannelList.get(i);
                if(ObjectUtil.isEmpty(authMap.get(appChannelDO.getCode()))){
                    continue;
                }
                log.info("merchantChannelRoute getSeqAllChannel start end:{} ",index);
                return CommonResult.success(appChannelDO);
            }
        }
        return CommonResult.error(0,"getSeqAllChannel 顺序单个机构轮询通道异常，未匹配到数据");
    }

    /**
     * 顺序AT轮询
     * @param merchantAppSubChannelDO
     * @param type
     * @param limitRouter
     * @param routerOrder
     * @return
     */
    private CommonResult<MerchantAccessAuthDO> getSeqAtChannel(PayOrderDO payOrderDO,PayWayDO payWayDO,MerchantAppChannelDO merchantAppSubChannelDO,Integer type,Integer limitRouter,Integer routerOrder,List<MerchantAppChannelDO> merchantAppChannelList){
        String sn = payOrderDO.getSn();
        String mchChannelCode = payOrderDO.getMchChannelCode();
        if (merchantAppSubChannelDO != null && merchantAppSubChannelDO.getAccessId() != null) {
            // 是否切换下个应用宝通道
            MerchantAppChannelDO MerchantAppChannelNew = null;
            // 子通道路由
            if (PayEnums.PAY_TYPE.WECHAT.getCode().equals(type) || PayEnums.PAY_TYPE.ALIPAY.getCode().equals(type)) {
                PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(type);
                // 查询AT通道
                List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,null,null);
                if(CollUtil.isNotEmpty(merchantAccessAuthList)){
                    log.info("merchantChannelRoute getSeqAtChannel merchantAppChannelList:{}", JSONUtil.toJsonStr(merchantAccessAuthList));
                    String autCode = payOrderDO.getAutCode();
                    if(StrUtil.isEmpty(autCode)){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常 当前没有autCode, sn:{},payOrderNo:{} ",sn,payOrderDO.getPayOrderNo());
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT通道异常");
                    }
                    // 通道编码顺序集合
                    List<String> seqList = new ArrayList<>();
                    for(MerchantAccessAuthDO merchantAccessAuthDO:merchantAccessAuthList){
                        seqList.add(merchantAccessAuthDO.getCode());
                    }
                    log.info("merchantChannelRoute getSeqAtChannel seqList:{} ",JSONUtil.toJsonStr(seqList));
                    // 位置
                    int index = seqList.indexOf(autCode);
                    log.info("merchantChannelRoute getSeqAtChannel start index:{},routerOrder:{} ",index,routerOrder);
                    if(index == -1){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常 当前通道不存在AT通道列表中,sn:{} ",sn);
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT轮询通道异常");
                    }
                    // 顺序
                    if(routerOrder == 0){
                        if(index == merchantAccessAuthList.size() - 1){
                            log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常,末尾无法继续向下轮询,则轮询下个应用通道 sn:{} ",sn);
                            // 继续取下一个通道
                            CommonResult<MerchantAppChannelDO> merchantAppChannelDOCommonResult = getSeqAllChannel(mchChannelCode,sn,merchantAppChannelList,payWayDO,routerOrder);
                            if(merchantAppChannelDOCommonResult.isSuccess() && merchantAppChannelDOCommonResult.getData() != null){
                                MerchantAppChannelNew = merchantAppChannelDOCommonResult.getData();
                                CommonResult<MerchantAccessAuthDO> authDOCommonResult = getNextAtChannel(MerchantAppChannelNew,sn,payType.getCode());
                                if(authDOCommonResult.isSuccess() && authDOCommonResult.getData() != null) {
                                    authDOCommonResult.getData().setMerchantAppChannelDO(MerchantAppChannelNew);
                                }
                                return authDOCommonResult;
                            }else{
                                return CommonResult.error(0,merchantAppChannelDOCommonResult.getMsg());
                            }
                        }
                        index = index + 1;
                    }else{
                        if(index == 0){
                            // 继续取下一个通道
                            CommonResult<MerchantAppChannelDO> merchantAppChannelDOCommonResult = getSeqAllChannel(mchChannelCode,sn,merchantAppChannelList,payWayDO,routerOrder);
                            if(merchantAppChannelDOCommonResult.isSuccess() && merchantAppChannelDOCommonResult.getData() != null){
                                MerchantAppChannelNew = merchantAppChannelDOCommonResult.getData();
                                CommonResult<MerchantAccessAuthDO> authDOCommonResult = getNextAtChannel(MerchantAppChannelNew,sn,payType.getCode());
                                if(authDOCommonResult.isSuccess() && authDOCommonResult.getData() != null) {
                                    authDOCommonResult.getData().setMerchantAppChannelDO(MerchantAppChannelNew);
                                }
                                return authDOCommonResult;
                            }else{
                                return CommonResult.error(0,merchantAppChannelDOCommonResult.getMsg());
                            }
                        }
                        index = index - 1;
                    }
                    log.info("merchantChannelRoute getSeqAtChannel start end:{} ",index);
                    // index 区间判断
                    if(index < 0 ||  index > merchantAccessAuthList.size() - 1){
                        log.error("merchantChannelRoute getSeqAtChannel 顺序单个机构轮询AT通道异常,轮询位置不在区间内 sn:{} ",sn);
                        return CommonResult.error(0,sn+":顺序单个机构轮询AT通道异常,轮询位置不在区间内");
                    }
                    return CommonResult.success(merchantAccessAuthList.get(index));
                }
            }
        }
        return CommonResult.error(0,"getSeqAtChannel 顺序单个机构轮询通道异常，未匹配到数据");
    }

    /**
     * 切换下一个通道
     * @param merchantAppSubChannelDO
     * @param sn
     * @param type
     * @return
     */
    private CommonResult<MerchantAccessAuthDO> getNextAtChannel(MerchantAppChannelDO merchantAppSubChannelDO,String sn,Integer type){
        if (merchantAppSubChannelDO != null && merchantAppSubChannelDO.getAccessId() != null) {
            // 子通道路由
            if (PayEnums.PAY_TYPE.WECHAT.getCode().equals(type) || PayEnums.PAY_TYPE.ALIPAY.getCode().equals(type)) {
                PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(type);
                // 查询AT通道
                List<MerchantAccessAuthDO> merchantAccessAuthList = merchantAccessAuthService.routerAccessAuthList(merchantAppSubChannelDO.getAccessId(), payType,null,null);
                if(CollUtil.isEmpty(merchantAccessAuthList)){
                    log.error("merchantChannelRoute getNextAtChannel 顺序单个机构轮询AT通道异常,切换通道查询AT通道列表为空 sn:{},mchChannelCode:{} ",sn,merchantAppSubChannelDO.getChannelCode());
                    return CommonResult.error(0,"切换通道查询AT通道列表为空");
                }
                // 获取已开启的AT通道列表
                List<MerchantAccessAuthDO> OpenAuthList = merchantAccessAuthList.stream().filter(merchantAccessAuthDO -> merchantAccessAuthDO.getState() != null && merchantAccessAuthDO.getState() == 1 ).collect(Collectors.toList());
                // 随机一个
                if(CollUtil.isNotEmpty(OpenAuthList)){
                    MerchantAccessAuthDO merchantAccessAuthDO = MerchantAppChannelRouterUtil.routerAt(OpenAuthList);
                    // 关闭其他AT通道状态
                    if(merchantAccessAuthDO != null){
                        for(MerchantAccessAuthDO authDO:OpenAuthList){
                            if(authDO.getId() != merchantAccessAuthDO.getId()){
                                MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                                updateMerchantAccessAuthDO.setState(0);
                                updateMerchantAccessAuthDO.setId(authDO.getId());
                                merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                            }
                        }
                    }
                    return CommonResult.success(merchantAccessAuthDO);
                }
                // 获取已关闭的AT通道列表
                List<MerchantAccessAuthDO> closeAuthList = merchantAccessAuthList.stream().filter(merchantAccessAuthDO -> merchantAccessAuthDO.getState() == null || merchantAccessAuthDO.getState() == 0 ).collect(Collectors.toList());
                if(CollUtil.isNotEmpty(closeAuthList)){
                    // 取第一个
                    MerchantAccessAuthDO merchantAccessAuthDO = closeAuthList.get(0);
                    // 开启状态
                    MerchantAccessAuthDO updateMerchantAccessAuthDO = new MerchantAccessAuthDO();
                    updateMerchantAccessAuthDO.setState(1);
                    updateMerchantAccessAuthDO.setId(merchantAccessAuthDO.getId());
                    merchantAccessAuthService.updateMerchantAccessAuth(updateMerchantAccessAuthDO);
                    return CommonResult.success(merchantAccessAuthDO);
                }
            }
        }
        return CommonResult.error(0,"无数据");
    }

    public void processOrderNotifyMessage(OrderStatusDto orderStatusDto) {
        PayOrderEnums.ORDER_STATUS_TYPE orderStatusType = PayOrderEnums.ORDER_STATUS_TYPE.from(orderStatusDto.getOrderStatusType());
        String orderNo = orderStatusDto.getOrderNo();
        if (!StringUtils.hasText(orderNo)) {
            log.info("收到的数据错误 orderNo:{}", orderNo);
            return;
        }
        switch (orderStatusType) {
            case PAY_ORDER_STATUS:
                PayOrderDO payOrderDO = payOrderService.queryPayOrder(orderNo);
                orderNotifyProcessHandler.notifyPayOrder(orderStatusDto, payOrderDO, null);
                break;
            case REFUND_STATUS:
                RefundOrderDO refundOrderDO = refundOrderService.queryRefundOrder(orderNo);
                orderNotifyProcessHandler.notifyRefundOrder(orderStatusDto, refundOrderDO, null);
                break;
            case PAYMENT_ORDER_STATUS:
                MerchantPaymentDetailDO merchantPaymentDetailDO = merchantPaymentService.queryPaymentDetail(orderNo);
                MerchantPaymentDO merchantPaymentDO = merchantPaymentService.queryDetail(merchantPaymentDetailDO.getPaymentId());
                orderNotifyProcessHandler.notifyPaymentOrder(orderStatusDto, merchantPaymentDO, merchantPaymentDetailDO, null);
                break;
            case MERCHANT_ACCESS_STATUS:
                MerchantAccessDto merchantAccessDto = merchantAccessService.domainDetailByRequestId(orderNo);
                orderNotifyProcessHandler.notifyMerchantAccess(orderStatusDto, merchantAccessDto, null);
                break;
            case MERCHANT_ACCESS_SETTLE_STATUS:
                OrderSettleDO accessSettleOrderDO = settleOrderService.queryByPayOrderNo(orderNo);
                orderNotifyProcessHandler.notifyMerchantAccessSettle(orderStatusDto, accessSettleOrderDO, null);
                break;
            case FUND_ORDER_STATUS:
                OrderFundDto orderFundDto = payOrderFundService.queryAcctOrderFundDto(orderNo);
                orderNotifyProcessHandler.notifyOrderFund(orderStatusDto, orderFundDto, null);
                break;
            case TRANSFER_ORDER_STATUS:
                OrderTransferDO orderTransferDO = transferOrderService.queryPayOrder(orderNo);
                orderNotifyProcessHandler.notifyOrderTransfer(orderStatusDto, orderTransferDO, null);
                break;
            case WITHDRAW_ORDER_STATUS:
                OrderWithdrawDO orderWithdrawDO = withdrawOrderService.queryPayOrder(orderNo);
                orderNotifyProcessHandler.notifyOrderWithdraw(orderStatusDto, orderWithdrawDO, null);
                break;
        }
    }

}
